<?php


namespace Aoe\Intent\Render;


use Aoe\Intent\Render\Http\HttpStatus;
use Aoe\Intent\Request\Http;
use Aoe\Intent\Request\Request;
use Aoe\Intent\Response;

/**
 * # http响应处理器
 */
abstract class Hypertext extends Render
{
    protected Request $request;
    protected string $statusText      = '';
    protected int    $statusCode      = 200;
    protected array  $responseHeaders = [];

    protected function __construct(protected Response $response)
    {
        parent::__construct($this->response);
        $this->request = $response->request;
    }

    protected function send(): void
    {
        ob_get_contents() && ob_clean();
        $this->_send_headers();

        /**
         * 抛出异常
         */
        if ($this->response->isException()) {
            $this->send_exception();
            return;
        }

        /**
         * 跳转
         */
        if ($this->response->isRedirect()) {
            $this->setStatusCode(302);
            $this->send_redirect();
            return;
        }

        $this->send_content();
    }
    
    abstract protected function send_exception(): void;
    
    abstract protected function send_redirect(): void;

    abstract protected function send_content(): void;
    
    /**
     * 发送Header 信息
     */
    private function _send_headers(): void
    {
        if (headers_sent()) return;

        if (!($this->request instanceof Http)) return;
        
        $statusCode = $this->statusCode;
        $version    = $this->request->version;
        header("HTTP/$version $statusCode $this->statusText");
        if (OPEN_CORS) $this->send_cors();
        if ($this->responseHeaders) {
            foreach ($this->responseHeaders as $name => $values) {
                $name = str_replace(
                    ' ',
                    '-',
                    ucwords(str_replace('-', ' ', $name)),
                );
                // set replace for first occurrence of header but false after-wards to allow multiple
                if (!is_array($values)) {
                    header("$name: $values");
                    continue;
                }
                $replace = true;
                foreach ($values as $value) {
                    header("$name: $value", $replace);
                    $replace = false;
                }
            }
        }
    }

    protected function send_header(string $name, ?string $value = ''): void
    {
        header("$name: $value");
    }
    
    /**
     * 设置状态码
     *
     * @param ?int    $value
     * @param ?string $text
     *
     * @return self
     */
    public function setStatusCode(?int $value = 200, ?string $text = null): Hypertext
    {
        if (!static::isInvalidStatusCode($value)) {
            $this->statusCode = $value;
            $this->statusText = $text ?? (HttpStatus::$httpStatuses[$this->statusCode] ?? '');
        }
        
        return $this;
    }
    
    protected static function isInvalidStatusCode(int $statusCode): bool
    {
        return $statusCode < 100 || $statusCode >= 600;
    }

    protected function send_cors(): void
    {
        if (isset($_SERVER['HTTP_ORIGIN'])) {
            header('Access-Control-Allow-Credentials: true');
            header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
            header("Access-Control-Allow-Headers: Content-Type");
        }
    }
}